home *** CD-ROM | disk | FTP | other *** search
/ Shareware Grab Bag / Shareware Grab Bag.iso / 007 / a86b.arc / EXPR.DOC < prev    next >
Text File  |  1986-06-23  |  16KB  |  447 lines

  1. ---EXPR.DOC---
  2.  
  3. Overview of Expressions
  4. -------- -- -----------
  5.  
  6. Most of the operands that you code into your instructions and data
  7. initializations will be simple register names, variable names, or constants.
  8. However, you will regularly wish to code operands that are the results of
  9. an arithmetic calculation, performed either by the machine when the program
  10. is running (for indexing), or by the assembler (to determine the value to
  11. assemble into the program).  A86 has a full set of operators that you can use
  12. to create expressions to cover these cases:
  13.  
  14. * Arithmetic Operators
  15.                      byte isolation and combination (HIGH, LOW, BY)
  16.                      addition and subtraction (+,-)
  17.                      multiplication and division (* , /, MOD)
  18.                      shifting operators (SHR, SHL, BIT)
  19.  
  20. * Logical Operators
  21.                      (AND, OR, XOR, NOT)
  22.  
  23. * Relational Operators
  24.                      (EQ, LE, LT, GE, GT, NE)
  25.  
  26. * Attribute Operators/Specifiers
  27.                      size specifiers (B=BYTE,W=WORD,F=FAR,SHORT,LONG)
  28.                      attribute specifiers (OFFSET,NEAR,brackets)
  29.                      segment-addressing specifier (:)
  30.                      compatibility operators (PTR,ST)
  31.                      built-in value specifiers (TYPE,THIS,$)
  32.  
  33. * Special Data Duplication Operator
  34.                      (DUP)  --see DB_DW_DD.DOC for a description
  35.  
  36.  
  37. Types of Expression Operands
  38. ----- -- ---------- --------
  39.  
  40. Numbers and Label Addresses
  41.  
  42. A number or constant (16-bit number) can be used in most expressions.   A label
  43. (defined with a colon) is also treated as a constant and so can be used in
  44. expressions, except when it is a forward reference.
  45.  
  46.  
  47. Variables
  48.  
  49. A variable stands for a byte- or word-memory location.   You may add or subtract
  50. constants from variables; when you do so, the constant is added to the address
  51. of the variable.  You typically do this when the variable is the name of a
  52. memory array.
  53.  
  54.  
  55. Index Expressions
  56.  
  57. An index expression consists of a combination of a base register [BX] or
  58. [BP], and/or an index register [SI] or [DI], with an optional constant added or
  59. subtracted.   You will usually want to precede the bracketed expression with
  60. B, W, or F; to specify the kind of memory unit (byte, word, or far-pointer)
  61. you are referring to.  The expression stands for the memory unit whose address
  62. is the run-time value(s) of the base and/or index registers added to the
  63. constant.  See EFF_ADDR.DOC for more details on indexed memory.
  64.  
  65.  
  66. Arithmetic Operators
  67. ---------- ---------
  68. HIGH/LOW
  69.  
  70. Syntax: HIGH operand
  71.         LOW operand
  72.  
  73. These operators are called the "byte isolation" operators.  The operand  must
  74. evaluate to a 16-bit number.   HIGH returns the high-order byte of the number;
  75. LOW the low-order byte.
  76.  
  77. For example,
  78.  
  79.   MOV AL,HIGH(01234)       ; AL = 012
  80.   TENHEX EQU LOW(0FF10)    ; TENHEX = 010
  81.  
  82. These operators can be applied to each other.   The following identities apply:
  83.  
  84. LOW LOW Q = LOW Q
  85. LOW HIGH Q = HIGH Q
  86. HIGH LOW Q = 0
  87. HIGH HIGH Q = 0
  88.  
  89.  
  90. BY
  91.  
  92. Syntax:  operand BY operand
  93.  
  94. This operator is a "byte combination" operator.  It returns the word whose
  95. high byte is the left operand, and whose low byte is the right operand.  For
  96. example, the expression 3 BY 5 is the same as hexadecimal 0305.  The BY
  97. operator is exclusive to A86.  I added it to cover the following situation:
  98. Suppose you are initializing your registers to immediate values.  Suppose
  99. you want to initialize AH to the ASCII value 'A', and AL to decimal 10.  You
  100. could code this as two instructions MOV AH,'A' and MOV AL,10; but you realize
  101. that a single load into the AX register would save both program space and
  102. execution time.  Without the BY operator, you would have to code MOV AX,0410A,
  103. which disguises the types of the individual byte-operands you were thinking
  104. about.  With BY, you can code it properly: MOV AX,'A' BY 10.
  105.  
  106.  
  107. Addition (combination)
  108.  
  109. Syntax: operand + operand
  110.         operand.operand
  111.         operand PTR operand
  112.         operand operand
  113.  
  114. As shown in the above syntax, addition can be accomplished in four ways: with a
  115. plus sign, with a dot operator, with a PTR operator, and simply by juxtaposing
  116. two operands next to each other.  The dot and PTR operators are provided for
  117. compatibility with Intel/IBM assemblers.  The dot is used in structure-field
  118. notation; PTR is used in expressions such as BYTE PTR 0.  (See COMPAT.DOC
  119. for recommendations concerning PTR.)
  120.  
  121. If either operand is a constant, the answer is an expression with the typing of
  122. the other operand, with the offsets added.  For example, if BVAR is a byte
  123. variable, then BVAR + 100 is the byte variable 100 bytes beyond BVAR.
  124.  
  125. Other examples:
  126.    DB 100+17         ; simple addition
  127.    CTRL EQU -040
  128.    MOV AL,CTRL'D'    ; juxtaposition provides a nice notation for control-D!
  129.    MOV DX,[BP].SMEM  ; --where SMEM was declared in an unindexed structure
  130.  
  131.  
  132. Subtraction
  133.  
  134. Syntax: operand - operand
  135.  
  136. The subtraction operator may have operands that are:
  137.  
  138. a.  both absolute numbers
  139. b.  variable names that have the same type
  140.  
  141. The result is an absolute number; the difference between the two operands.
  142.  
  143.  
  144. Multiplication and Division
  145.  
  146. Syntax:
  147.   Multiplication: operand * operand
  148.   Division:       operand / operand
  149.   Modulo:         operand MOD operand
  150.  
  151. You may only use these operators with absolute numbers, and the result is always
  152. an absolute number.  Either operand may be a numeric expression, as long as the
  153. expression evaluates to an absolute number.  Examples:
  154.  
  155. CMP AL, 2 * 4    ; compare AL to 8
  156. MOV BX, 0123/16  ; BX = 012
  157.  
  158.  
  159. Shifting Operators
  160.  
  161. Syntax: Shift right: operand SHR count
  162.         Shift left: operand SHL count
  163.         Bit number: BIT count
  164.  
  165. The shift operators will perform a "bit-wise" shift of the operand.  The operand
  166. will be shifted "count" bits either to the right or the left.  Bits shifted into
  167. the operand will be set to 0.
  168.  
  169. The expression "BIT count" is equivalent to "1 SHL count"; i.e., BIT returns
  170. the mask of the single bit whose number is "count".  The operands must be
  171. numeric expressions that evaluate to absolute numbers.  Examples:
  172.  
  173. MOV BX, 0FACBH SHR 4   ; BX = 0FACH
  174. OR AL,BIT 6            ; AL = AL OR 040 -- 040 is the mask for bit number 6
  175.  
  176.  
  177. Logical Operators
  178. ------- ---------
  179. Syntax: operand OR operand
  180.         operand XOR operand
  181.         operand AND operand
  182.         NOT operand
  183.  
  184. The logical operators may only be used with absolute numbers.  They always
  185. return an absolute number.
  186.  
  187. Logical operators operate on individual bits.   Each bit of the answer depends
  188. only on the corresponding bit in the operand(s).
  189.  
  190. The functions performed are as follows:
  191.  
  192. 1.  OR: An answer bit is 1 if either or both of the operand bits is 1.   An
  193. answer bit is 0 only if both operand bits are 0.   Example:
  194.  
  195. 11110000xB OR 00110011xB = 11110011xB
  196.  
  197.  
  198. 2.  XOR: This is "exclusive OR."  An answer bit is 1 if the operand bits are
  199. different; an answer bit is 0 if the operand bits are the same.   Example:
  200.  
  201. 11110000xB XOR 00110011xB = 11000011xB
  202.  
  203.  
  204. 3.  AND: An answer bit is 1 only if both operand bits are 1.   An answer bit is
  205. 0 if either or both operand bits are 0.   Example:
  206.  
  207. 11110000xB AND 00110011xB = 00110000xB
  208.  
  209. 4.  NOT: An answer bit is the opposite of the operand bit.   It is 1 if the
  210. operand bit is 0; 0 if the operand bit is 1.   Example:
  211.  
  212. NOT 00110011xB = 11001100xB
  213.  
  214.  
  215. Relational Operators
  216. ---------- ---------
  217. Syntax:
  218.   equal:            operand EQ operand
  219.   not equal:        operand NE operand
  220.   less than:        operand LT operand
  221.   less or equal:    operand LE operand
  222.   greater than:     operand GT operand
  223.   greater or equal: operand GE operand
  224.  
  225. The relational operators may have operands that are:
  226.  
  227. a.  both absolute numbers
  228. b.  variable names that have the same type
  229.  
  230. The result of a relational operation is always an absolute number.  They return
  231. an 8-or 16-bit result of all 1's for TRUE and all 0's for FALSE.  Examples:
  232.  
  233. MOV AL, 3 EQ 0     ; AL = 0 (false)
  234. MOV AX, 2 LE 15    ; AX = 0FFFFH (true)
  235.  
  236.  
  237. Attribute Operators/Specifiers
  238. --------- --------------------
  239. B,W,F memory-variable specifiers
  240.  
  241. Syntax: B operand
  242.         operand B
  243.         W operand
  244.         operand W
  245.         F operand
  246.         operand F
  247.  
  248. B, W, and F convert the operand into a BYTE, WORD, and DOUBLEWORD variable,
  249. respectively.  The operand can be a constant, or a variable of the other type.
  250. Examples:
  251.  
  252. ARRAY_PTR:
  253.   DB 100 DUP (?)
  254. WVAR  DW ?
  255.   MOV AL,ARRAY_PTR B      ; loads the first byte of ARRAY_PTR array into AL
  256.   MOV AL,WVAR B           ; load the low byte of WVAR into AL
  257.   MOV AX,W[01000]         ; load AX with the memory-word at location 01000
  258.   LDS BX,F[01000]         ; load DS:BX with the doubleword at location 01000
  259.  
  260. For compatibility with Intel/IBM assemblers, A86 accepts the more verbose
  261. synonyms BYTE, WORD, and FAR for B,W,F, respectively.
  262.  
  263.  
  264. SHORT and LONG operators
  265.  
  266. Syntax:   SHORT label
  267.           LONG label
  268.  
  269. The SHORT operator is used to specify that the label referenced by a JMP
  270. instruction is within 127 bytes of the end of the instruction.  The LONG
  271. operator specifies the opposite: that the label is not within 127 bytes.  The
  272. appropriate operator can (and sometimes must) be used if the label is forward
  273. referenced in the instruction.
  274.  
  275. When a non-local label is forward referenced, the assembler assumes that it will
  276. require two bytes to represent the relative offset of the label. By correctly
  277. using the SHORT operator, you can save a byte of code when you use a forward
  278. reference. If the label is not within the specified range, an error will occur.
  279. The following example illustrates the use of the SHORT operator.
  280.  
  281. JMP FWDLAB        ;three byte instruction
  282. JMP SHORT FWDLAB  ;two byte instruction
  283. JMP >L1           ; two byte instruction automatically assumed for a local label
  284.  
  285. Because the assembler assumes that a forward-reference local label is SHORT,
  286. you may sometimes be forced to override this assumption if the label is in fact
  287. not within 127 bytes of the JMP.  This is why LONG is provided:
  288.  
  289. JMP LONG >L9      ; three byte instruction
  290.  
  291. NOTE that LONG will have effect only on the operand to an unconditional JMP
  292. instruction; not to conditional jumps.  This is because the conditional jumps
  293. don't have 3-byte forms; the only conditional jumps are short ones.  If you
  294. run into this problem, then chances are your code is getting out of control--
  295. time to rearrange, or to break off some of the intervening code into separate
  296. procedures.  If you insist upon leaving the code intact, you can replace the
  297. conditional jump with an "IF cond JMP".
  298.  
  299.  
  300. OFFSET operator
  301.  
  302. Syntax: OFFSET var-name
  303.  
  304. OFFSET is used to convert a variable into the constant pointer to the variable.
  305. For example, if you have declared  XX DW ?, and you want to load SI with the
  306. pointer to the variable XX, you can code: MOV SI,OFFSET XX.  The simpler
  307. instruction MOV SI,XX moves the variable contents of XX into SI, not the
  308. constant pointer to XX.
  309.  
  310.  
  311. NEAR Operator
  312.  
  313. Syntax: NEAR operand
  314.  
  315. NEAR converts the operand to have the type of a code label, as if it were
  316. defined by appearing at the beginning of a program line with a colon after it.
  317. NEAR is provided mainly for compatibility with Intel/IBM assemblers.
  318.  
  319. Square Brackets Operator
  320.  
  321. Syntax: [operand]
  322.  
  323. Square brackets around an operand give the operand a memory-variable type.
  324. Square brackets are generally used to enclose the names of base and index
  325. registers: BX, BP, SI, and DI.  When the size of the memory variable can be
  326. deduced from the context of the expression, they are also used to turn numeric
  327. constants into memory variables.  Examples:
  328.  
  329.   MOV B[BX+50],047 ; move immediate value 047 into memory byte at BX+50
  330.   MOV AL,[050]     ; move byte at memory loaction 050 into AL
  331.   MOV AL,050       ; move immediate value 050 into AL
  332.  
  333.  
  334. Colon Operator
  335.  
  336. Syntax:  constant:operand
  337.          segreg:operand
  338.  
  339. The colon operator is used to attach a segment-register value to an operand.
  340. The segment-register value appears to the left of the colon; the rest of the
  341. operand appears to the right of the colon.
  342.  
  343. There are two forms to the colon operator.  The first form has a constant as
  344. the segment-register value.  This form is used to create an operand to a long
  345. (inter-segment) JMP or CALL instruction.  An example of this is the instruction
  346. JMP 0FFFF:0, which jumps to the cold-boot reset location of the 86 processor.
  347.  
  348. The only context other than JMP or CALL in which this first form is legal, is as
  349. the operand to a DD directive or an EQU directive.  The EQU case has a further
  350. restriction: the offset (the part to the right of the colon) must have a value
  351. less than 256.  This is becuase there simply isn't room in a symbol-table entry
  352. for a segment-register value AND a 2-byte offset.  I don't think you will be
  353. hurt by this restriction, since references to other segments are usually to
  354. jump-tables at the beginning of those segments.
  355.  
  356. The second form has a segment register name to the left of the colon.  This
  357. is the segment-oveeride form, provided for compatibility with Intel/IBM
  358. assebmlers.  A86 will generate a segment-override byte when it sees this
  359. form, unless the operand to the right of the colon already has a default
  360. segment register that is the same as the given override.
  361.  
  362. I prefer the more explicit method of overrides, exclusive to A86: simply place
  363. the segment register name before the instruction mnemonic.  For example, I
  364. prefer ES MOV AL,[BX] to MOV AL,ES:[BX].
  365.  
  366.  
  367. ST Operator
  368.  
  369. ST is ignored whenever it occurs in an expression.  It is provided for
  370. compatibility with Intel and IBM assemblers.
  371.  
  372. TYPE Operator
  373.  
  374. Syntax: TYPE operand
  375.  
  376. The TYPE operator returns 1 if the operand is a byte variable; 2 if the operand
  377. is a word variable; 4 if the operand is a doubleword variable; and the number
  378. of bytes allocated by the strucure if the operand is a structure name.
  379.  
  380.  
  381. THIS and $ Specifiers
  382.  
  383. THIS returns the value of the current location counter.  It is provided for
  384. compatibility with Intel/IBM assemblers.  The dollar-sign $ is the more
  385. standard and familiar specifier for this purpose; it is equivalent to THIS
  386. NEAR.  THIS is typically used with the BYTE and WORD specifiers to create
  387. alternate-typed symbols at the same memory location:
  388.  
  389.      BVAR EQU THIS BYTE
  390.      WVAR  DW ?
  391.  
  392. I don't recommend the use of THIS.  If you wish to retain Intel-compatibility,
  393. you can use the less-verbose LABEL directive:
  394.  
  395.       BVAR LABEL BYTE
  396.       WVAR  DW ?
  397.  
  398. If you are not concerned with compatibility to lesser assemblers, A86 offers
  399. a variety of less-verbose forms.  The most concise is DB without an operand:
  400.  
  401.       BVAR DB
  402.       WVAR DW ?
  403.  
  404. If this is too cryptic for you, there is always BVAR EQU B[$].
  405.  
  406.  
  407. Operator Precedence
  408. -------- ----------
  409. Consider the expression 1 + 2 * 3.  When A86 sees this expression, it could
  410. perform the multiplication first, giving an answer of 1+6 = 7; or it could do
  411. the addition first, giving an answer of 3*3 = 9.  In fact, A86 does the
  412. multiplication first, because A86 assigns a higher precedence to multiplication
  413. than it does addition.
  414.  
  415. The following list specifies the order of precedence A86 assigns to
  416. expression operators. All expressions are evaluated from left to right
  417. following the precedence rules.  You may override this order of evaluation and
  418. precedence through the use of parentheses ().  In the example above, you could
  419. override the precedence by parenthesizing the addition: (1+2) * 3.
  420.  
  421. Some symbols that we have referred to as operators, are treated by the
  422. assembler as operands having built-in values.  These include B, W, F, $, and
  423. ST.
  424.  
  425. If two operators are adjacent, the rightmost operator must have precedence;
  426. otherwise, parentheses must be used.
  427.  
  428. ---Highest Precedence---
  429.  
  430. 1.  Parenthesized expressions
  431. 2.  Period
  432. 3.  OFFSET, TYPE, and PTR
  433. 4.  HIGH, LOW, and BIT
  434. 5.  Multiplication and division: *, /, MOD, SHR, SHL
  435. 6.  Addition and subtraction: +,-
  436.      a. unary
  437.      b. binary
  438. 7.  Relational: EQ, NE, LT, LE, GT, GE
  439. 8.  Logical NOT
  440. 9.  Logical AND
  441. 10. Logical OR and XOR
  442. 11. Colon, SHORT, LONG, and BY
  443. 12. DUP
  444.  
  445. ---Lowest Precedence---
  446.  
  447.